package tr.edu.metu.is.mega.server.core;

import java.util.List;
import java.util.Map;

import org.eclipse.persistence.expressions.Expression;

/**
 * Common interface for all data access objects.
 * 
 * @param <T> type modifier for entity
 * @param <IdT> type modifier for primary key class
 */
public interface DAO<T extends BaseEntity, IdT> {

    /**
     * Create an entity record.
     * 
     * @param entity entity instance to record
     * @return created entity instance
     */
    T create(T entity);

    /**
     * Updates an existing entity record.
     * 
     * @param entity entity record
     * @return updated entity
     */
    T update(T entity);

    /**
     * Returns an entity record by its identifier.
     * 
     * @param id entity identifier
     * @return entity record
     */
    T findById(IdT id);

    /**
     * Deletes an existing entity record.
     * 
     * @param entity entity record
     */
    void delete(T entity);

    /**
     * Deletes an entity by its identifier.
     * 
     * @param id identifier of the entity
     */
    void deleteById(IdT id);

    /**
     * Returns all records of an entity type.
     * 
     * @return list of records
     */
    List<T> loadAll();

    /**
     * Returns all records of an entity type as paging.
     * 
     * @param params paging parameters
     * @return list of entities
     */
    List<T> loadAll(PagedQueryParams params);

    /**
     * Queries entities as filtering using example instance values.
     * 
     * @param example example instance
     * @param useLike a like query is conducted when true
     * @return list of entities
     */
    List<T> findByExample(T example, boolean useLike);

    /**
     * Queries entities as filtering using example instance values and with
     * paging.
     * 
     * 
     * @param example example instance
     * @param useLike a like query is conducted when true
     * @param params paging parameters
     * @return list of entities
     */
    List<T> findByExample(T example, boolean useLike, PagedQueryParams params);

    /**
     * Returns number of records matching search criteria.
     * 
     * @param example filter criteria
     * @param useLike a like query is conducted when true
     * @return number of records
     */
    Long getCountByExample(T example, boolean useLike);

    /**
     * Returns list of entities filtering by a map of property name-value pairs.
     * 
     * @param params map of property name-value pairs
     * @return list of entities
     */
    List<T> findByParams(Map<String, Object> params);

    /**
     * Makes a
     * "select * from T where <I><B>fieldName</B></I> IN (<B><I>prms</I></B>)"
     * query.
     * 
     * 
     * @param fieldName field name
     * @param prms parameters
     * @return list of entities
     */
    List<T> findByMultipleValue(String fieldName, Object... prms);

    /**
     * Returns list of entities having specified primary key values.
     * 
     * 
     * @param ids list of primary key values
     * @return list of entities
     */
    List<T> findByIdList(IdT... ids);

    /**
     * Returns number of records.
     * 
     * @return number of records
     */
    Long getRecordCount();

    /**
     * Deletes entity records with the specified primary key values.
     * 
     * @param idList list of primary key values
     */
    void deleteByIdList(List<IdT> idList);

    /**
     * Returns list of records matching given criteria and expression.
     * 
     * @param example example instance to be used for filtering
     * @param useLike like query indicator
     * @param params paging parameters
     * @param expr expression
     * @return list of records
     */
    List<T> findByExample(T example, boolean useLike, PagedQueryParams params,
            Expression expr);

    /**
     * Returns count of records matching given criteria and expression.
     * 
     * @param example example instance to be used for filtering
     * @param useLike like query indicator
     * @param expr expression
     * @return list of records
     */
    Long getCountByExample(T example, boolean useLike, Expression expr);

    /**
     * Makes a native query and returns matching records.
     * 
     * @param queryName name of the named native query
     * @param params key = index of parameter, value = value of parameter
     * @return list of records
     */
    List<T> findByNamedNativeQuery(String queryName, Map<Integer, Object> params);

    /**
     * Makes a native query and returns single result.
     * 
     * @param queryName name of query
     * @param params query parameters
     * @param <X> type modifier
     * @return query result
     */
    <X> X findSingleResultByNamedNativeQuery(String queryName,
            Map<Integer, Object> params);

    /**
     * Makes a named query and returns matching records.
     * 
     * @param queryName name of query
     * @param params query parameters
     * @return matching records
     */
    List<T> findByNamedQuery(String queryName, Map<String, Object> params);

    /**
     * Makes a named query and returns single result.
     * 
     * @param queryName name of query
     * @param params query parameters
     * @param <X> returning type modifier
     * @return matching records
     */
    <X> X findSingleResultByNamedQuery(String queryName,
            Map<String, Object> params);

    /**
     * Makes and EJB-QL query and returns list of records.
     * 
     * @param query query string
     * @param params query parameters
     * @param pagingParams paging parameters
     * @return list of records
     */
    List<T> findByQuery(String query, Map<String, Object> params,
            PagedQueryParams pagingParams);

    /**
     * Makes and EJB-QL query and returns number of matching records.
     * 
     * @param query query string
     * @param params query parameters
     * @return number of records
     */
    Long findByQueryCount(String query, Map<String, Object> params);

}
